home *** CD-ROM | disk | FTP | other *** search
- Path: xanth!ukma!mailrus!ulowell!page
- From: page@swan.ulowell.edu (Bob Page)
- Newsgroups: comp.sources.amiga
- Subject: v89i065: proc - createproc() w/o loadseg()
- Message-ID: <12257@swan.ulowell.edu>
- Date: 15 Mar 89 21:55:02 GMT
- Organization: University of Lowell, Computer Science Dept.
- Lines: 475
- Approved: page@swan.ulowell.edu
-
- Submitted-by: well!ewhac (Leo 'Bols Ewhac' Schwab)
- Posting-number: Volume 89, Issue 65
- Archive-name: dos/proc.1
-
- # This is a shell archive.
- # Remove everything above and including the cut line.
- # Then run the rest of the file through sh.
- #----cut here-----cut here-----cut here-----cut here----#
- #!/bin/sh
- # shar: Shell Archiver
- # Run the following text with /bin/sh to create:
- # README
- # proc.c
- # proc.uu
- # This archive created: Wed Mar 15 16:53:01 1989
- cat << \SHAR_EOF > README
- This is a little goodie I cooked up as a simple diversion before I
- started back into working on "Onion". This is written in Manx C 3.4b.
- Translation to Lattice should be straightforward.
-
- MANUFACTURE:
- 1> cc proc.c
- 1> ln proc.o -lc
-
- That's all there is to it. The source code has copious comments,
- which I hope illustrate what's going on. Perhaps some CATS people would
- care to comment on just how supportable this trick is.
-
- I hope you like it.
-
- _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
- Leo L. Schwab -- The Guy in The Cape INET: well!ewhac@ucbvax.Berkeley.EDU
- \_ -_ Recumbent Bikes: UUCP: pacbell > !{well,unicom}!ewhac
- O----^o The Only Way To Fly. hplabs / (pronounced "AE-wack")
- "Work FOR? I don't work FOR anybody! I'm just having fun." -- The Doctor
- SHAR_EOF
- cat << \SHAR_EOF > proc.c
- /* :ts=8 bk=0
- *
- * proc.c: Illustration of how to create a full-fledged DOS process
- * without needing to LoadSeg() it first. Based on an idea
- * presented at BADGE (don't remember the name of the guy
- * who thought it up).
- *
- * Leo L. Schwab 8903.01
- */
- #include <exec/types.h>
- #include <libraries/dosextens.h>
-
- extern void *AllocMem(), *CreatePort(), *GetMsg(), *FindTask();
-
- extern LONG Open(), Output(), CreateProc();
-
-
- /*
- * Cursor manipulation strings.
- */
- char fwdcursor[] = "\033[C";
- char backcursor = '\b';
-
- /*
- * Buried deep in the AmigaDOS Technical Reference Manual, the structure of
- * of memory lists and SegLists are described. A SegList consists of a BPTR
- * to the next element in the list (NULL-terminated), followed by code.
- * The pointers point to the NextSeg field. The size of the node in bytes
- * is stored in the longword just before NextSeg field. However, the
- * size is only of real interest to UnLoadSeg(), which you won't be calling
- * in this case. So we don't need it.
- *
- * So the PhonySegList structure consists merely of a NextSeg field, which
- * is initialized to NULL (CreateProc() ignores this field, anyway), followed
- * by code to execute, which CreateProc() will jump to. The code we give it
- * to execute is an absolute jump to the real entry point, which you
- * initialize appropriately.
- */
- struct PhonySegList {
- BPTR psl_NextSeg; /* BPTR to next element in list */
- UWORD psl_JMP; /* A 68000 JMP abs.l instruction */
- LONG (*psl_EntryPoint)(); /* The address of the function */
- };
-
- /*
- * This is NOT the structure that will actually get passed to CreateProc().
- * AmigaDOS demands that everything, including SegLists, be on longword
- * boundaries. Short of compiler-dependent switches, the only way to
- * guarantee correct alignment is to AllocMem() a PhonySegList structure,
- * and copy this template into it. You should also remember to initialize
- * the psl_EntryPoint field (the argument to the JMP instruction) in the
- * allocated structure, for obvious reasons.
- */
- struct PhonySegList template = {
- NULL, /* No next element. */
- 0x4EF9, /* JMP abs.l */
- NULL /* Argument for JMP instruction */
- };
-
-
- /*
- * This is the routine that will be CreateProc()ed. Due to the global nature
- * of library base variables, any library routines this routine calls will
- * be using library base variables that, strictly speaking, belong to the
- * "parent" process. Despite the fact that it will work, this is
- * nevertheless a dangerous practice. In an ideal world, you would want to
- * convince the linker to resolve all library base pointer references to
- * your co-process's own copies. Lattice, on the other hand, due to its
- * #pragmas, may not have this problem (can someone confirm this?).
- */
- LONG
- coprocess ()
- {
- register int i, n;
- struct Process *me;
- struct Message *startupmsg;
- LONG doswin;
- char buf[256];
-
- #ifdef AZTEC_C
- #ifndef _LARGE_DATA
- /*
- * This gets to be a bloody nuisance.
- */
- geta4 ();
- #endif
- #endif
- /*
- * Startup messages are important. Not only can they provide
- * configuration information for the newly-created process (what
- * directory you're in, what size to make your window, etc.), but
- * they also serve to inform the program that started you that
- * you have finished executing. This is important, because the
- * parent program will want to know when it's okay to free the
- * resources it allocated to start you. In this example, we
- * grab the message so that we can reply it. The act of replying
- * the startup message will inform the parent that we're done.
- */
- me = FindTask (NULL);
- WaitPort (&me -> pr_MsgPort);
- startupmsg = GetMsg (&me -> pr_MsgPort);
-
- /*
- * Recall that, because a global DOSBase pointer has been initialized
- * by the parent, and because the stubs will reference it at the link
- * stage, we don't need to open dos.library here.
- */
- if (!(doswin = Open ("CON:0/0/320/100/Sub-Process", MODE_NEWFILE)))
- goto xit;
-
- /*
- * Say hello.
- */
- Write (doswin, "This is the child speaking.\n", 28L);
-
- /*
- * Print the value of FindTask(NULL) to prove we're a separate
- * task, and print some values in the Process structure to prove
- * we're a real process.
- *
- * (Another caveat: The stdio functions in this example (like
- * sprintf()) are being shared by both processes. Some stdio
- * routines utilize a set of global variables, access to which is
- * not arbitrated. Therefore, it is possible for the processes to
- * collide when calling stdio functions, causing Bad Things to
- * happen. Be aware of this when doing your own multiprogramming.
- * (I'm pretty sure sprintf() is safe.))
- */
- sprintf (buf, "I'm at 0x%lx\n", me);
- Write (doswin, buf, (LONG) strlen (buf));
-
- sprintf (buf, "My stack size appears to be\n%ld bytes.\n",
- me -> pr_StackSize);
- Write (doswin, buf, (LONG) strlen (buf));
-
- sprintf (buf, "pr_StackBase is 0x%lx\n", me -> pr_StackBase);
- Write (doswin, buf, (LONG) strlen (buf));
-
- /*
- * Make the cursor in the window zot back and forth, which will
- * happen concurrently with the same action in the CLI window,
- * proving beyond a shadow of a doubt that there really are two
- * separate programs running.
- */
- for (n = 20; n--; ) {
- for (i = 35; i--; )
- Write (doswin, fwdcursor, sizeof (fwdcursor) - 1L);
- for (i = 35; i--; )
- Write (doswin, &backcursor, 1L);
- }
-
- /*
- * We've proved our existence. We now reply our startup message,
- * and exit. Note the use of Forbid() without a corresponding
- * Permit(). This prevents this process from being switched out
- * before exiting completely. When this process is totally gone,
- * Exec will notice, and do the equivalent of a Permit() internally.
- */
- Close (doswin); /* Get ridda da window. */
- xit:
- Forbid ();
- ReplyMsg (startupmsg);
- return (0);
- }
-
-
- /*
- * Here is the main program. Its job will be to create the support
- * structures to fire off the sub-process, print out some relevant
- * information, then while away the time until the child exits.
- */
- main ()
- {
- register int i;
- struct Process *me;
- struct MsgPort *replyport = NULL;
- struct Message startupmsg;
- struct PhonySegList *fakelist = NULL;
- LONG child,
- priority,
- term;
-
- /*
- * Get a handle on the current output stream so that we can Write()
- * to it. Note that this implies this program really ought to be
- * run from a CLI.
- */
- if (!(term = Output ()))
- goto xit;
-
- /*
- * Create a message port for the startup message to be replied to.
- */
- if (!(replyport = CreatePort (NULL, NULL)))
- goto xit;
-
- /*
- * Allocate a PhonySegList structure.
- */
- if (!(fakelist = AllocMem ((LONG) sizeof (*fakelist), NULL)))
- goto xit;
-
- /*
- * Copy the template into the allocated memory, and set the entry
- * point to the sub-process.
- */
- CopyMem (&template, fakelist, (LONG) sizeof (template));
- fakelist -> psl_EntryPoint = coprocess;
-
- /*
- * Initialize the startup message. There's nothing really amazing
- * happening here. Its sole purpose in life is to be replied.
- */
- startupmsg.mn_Node.ln_Type = NT_MESSAGE;
- startupmsg.mn_Node.ln_Pri = 0;
- startupmsg.mn_ReplyPort = replyport;
-
- /*
- * Find ourselves. Discover what priority we're running at, so that
- * we can start the sub-process at the same priority.
- */
- me = FindTask (NULL);
- priority = me -> pr_Task.tc_Node.ln_Pri;
-
- /*
- * Print some information about ourselves.
- */
- puts ("This is the parent speaking.");
- printf ("I'm at 0x%lx\n", me);
- printf ("My stack size appears to be\n%ld bytes.\n",
- me -> pr_StackSize);
- printf ("pr_StackBase is 0x%lx\n", me -> pr_StackBase);
-
- /*
- * Now, create and start the sub-process. The current release of
- * AmigaDOS CreateProc() does nothing special with SegLists.
- * All it uses it for is to find the first bit of code to execute.
- * By passing it 'fakelist', we're essentially feeding it a JMP
- * instruction which jumps to the real start of our sub-process.
- * (Note that we have to convert 'fakelist' into a BPTR.)
- * Thus, we get a full-fledged DOS process, which we can do things
- * with, and we didn't have to LoadSeg() it.
- */
- if (!(child = CreateProc ("Sub-Process",
- priority,
- (LONG) fakelist >> 2,
- 2048L)))
- goto xit;
-
- /*
- * Send the startup message. This will get the sub-process doing
- * its thing.
- * (Note that CreateProc() returns a pointer, not to the process
- * structure, but to the pr_MsgPort structure *within* the process
- * structure.)
- */
- PutMsg (child, &startupmsg);
-
- /*
- * Make our cursor fly back and forth, which hopefully will happen
- * concurrently with the sub-process's activity. We continue to
- * do this until the sub-process replies its message, making
- * GetMsg() return a non-NULL value. Since we "know" what's arriving
- * at the replyport, we can safely throw the result from GetMsg()
- * away.
- */
- while (!GetMsg (replyport)) {
- for (i = 64; i--; )
- Write (term, fwdcursor, sizeof (fwdcursor) - 1L);
- for (i = 64; i--; )
- Write (term, &backcursor, 1L);
- }
-
- /*
- * At this point, the sub-process has completely exited. We may
- * now safely deallocate all the support structures, and exit.
- */
- puts ("Child terminated.");
- xit:
- if (fakelist) FreeMem (fakelist, (LONG) sizeof (*fakelist));
- if (replyport) DeletePort (replyport);
- }
- SHAR_EOF
- cat << \SHAR_EOF > proc.uu
-
- begin 644 proc
- M```#\P`````````#``````````(```61````J@````$```/I```%D4[Z`_I.1
- M5?[T2.<,`$ZZ!&!"ITZZ%5183RM`__P@;?_\2&@`7$ZZ%>A83R!M__Q(:`!<I
- M3KH5<%A/*T#_^$AX`^Y(>@$P3KH3O%!/*T#_]&<``0I(>``<2'H!-B\M__1.R
- MNA/`3^\`#"\M__Q(>@$_2&W^]$ZZ"#9/[P`,2&W^]$ZZ#.)83TC`+P!(;?[T)
- M+RW_]$ZZ$XY/[P`,(&W__"\H`(1(>@$72&W^]$ZZ"`!/[P`,2&W^]$ZZ#*Q8_
- M3TC`+P!(;?[T+RW_]$ZZ$UA/[P`,(&W__"\H`)!(>@$)2&W^]$ZZ!\I/[P`,^
- M2&W^]$ZZ#'983TC`+P!(;?[T+RW_]$ZZ$R)/[P`,>A1@0'@C8!1(>``#2&R``
- M`B\M__1.NA,&3^\`##`$4T1*0&;D>"-@%$AX``%(;(`&+RW_]$ZZ$N9/[P`,^
- M,`131$I`9N0P!5-%2D!FN"\M__1.NA)46$].NA0<+RW_^$ZZ%(Q83W``3-\`M
- M,$Y=3G5#3TXZ,"\P+S,R,"\Q,#`O4W5B+5!R;V-E<W,`5&AI<R!I<R!T:&4@%
- M8VAI;&0@<W!E86MI;F<N"@!))VT@870@,'@E;'@*`$UY('-T86-K('-I>F4@2
- M87!P96%R<R!T;R!B90HE;&0@8GET97,N"@!P<E]3=&%C:T)A<V4@:7,@,'@EO
- M;'@*`$Y5_]0O!$*M__A"K?_@3KH2#"M`_]1G``$Z0J="ITZZ$E103RM`__AGY
- M``$H0J=(>``*3KH3*E!/*T#_X&<``11(>``*+RW_X$AL@`A.NA(43^\`#$'ZZ
- M_;8B;?_@(T@`!AM\``7_[$(M_^TK;?_X__)"ITZZ$OQ83RM`__P@;?_\$"@``
- M"4B`2,`K0/_82'H`[DZZ!3)83R\M__Q(>@#]3KH&7E!/(&W__"\H`(1(>@#YP
- M3KH&3%!/(&W__"\H`)!(>@$/3KH&.E!/2'@(`"`M_^#D@"\`+RW_V$AZ`0Q.X
- MNA#D3^\`$"M`_]QG:$AM_^0O+?_<3KH2ZE!/+RW_^$ZZ$JY83TJ`9D)X0&`4C
- M2'@``TAL@`(O+?_43KH1$$_O``PP!%-$2D!FY'A`8!1(>``!2&R`!B\M_]1.>
- MNA#P3^\`##`$4T1*0&;D8+!(>@"H3KH$=EA/2JW_X&<.2'@`"B\M_^!.NA(J:
- M4$]*K?_X9PHO+?_X3KH1CEA/*!].74YU5&AI<R!I<R!T:&4@<&%R96YT('-PV
- M96%K:6YG+@!))VT@870@,'@E;'@*`$UY('-T86-K('-I>F4@87!P96%R<R!T!
- M;R!B90HE;&0@8GET97,N"@!P<E]3=&%C:T)A<V4@:7,@,'@E;'@*`%-U8BU0$
- M<F]C97-S`$-H:6QD('1E<FUI;F%T960N`&%P0^R"8D7L@F*UR68.,CP`$6L(+
- M=``BPE')__PI3X)J+'@`!"E.@FY(YX"`""X`!`$I9Q!+^@`(3J[_XF`&0J?S6
- M7TYS0_H`($ZN_F@I0()R9@PN/``#@`=.KO^48`1.N@`:4$].=61O<RYL:6)RV
- M87)Y`$GY``!__DYU3E4``"\*2'D``0``,"R"7L'\``8O`$ZZ$,PI0()V4$]FD
- M%$*G2'D``0``3KH/D%!/+FR":DYU(&R"=D)H``0@;()V,7P``0`0(&R"=C%\S
- M``$`"B!L@FH@+()JD*@`!%"`*4"">B!L@GH@O$U!3EA"ITZZ$(0D0$JJ`*Q8E
- M3V<N+RT`#"\M``@O"DZZ`*XY?``!@GX@;()V`&B````$(&R"=@!H@```"D_OY
- M``Q@0DAJ`%Q.NA#J2&H`7$ZZ$'@I0(*`(&R"@$JH`"103V<0(&R"@")H`"0OL
- M$4ZZ#H!83R\L@H`O"DZZ`IPI;(*`@H103TZZ#H`@;()V((!.N@ZH(&R"=B%`C
- M``9G%DAX`^U(>@`J3KH.@"!L@G8A0``,4$\O+(*$/RR"B$ZZ_%Q"9TZZ#+!0X
- M3R1?3EU.=2H`3E4``$CG##`D;0`0(&T`""`H`*SE@"@`($0@*``0Y8`F0!`39
- M2(!(P-"M``Q4@#E`@HI"IS`L@HI(P"\`3KH/;BE`@HQ03V8(3-\,,$Y=3G40H
- M$TB`.@`_!2!+4H@O""\L@HQ.N@%.2'H!2#`%2,#0K(*,+P!.N@&(/RT`#B\*:
- M+RR"C$ZZ`58@;(*,0C!0`#E\``&"B#`%2,#0K(*,)D!2BR1+3^\`'!`32(`Z<
- M`+!\`"!G&+I\``EG$KI\``QG#+I\``UG!KI\``IF!%*+8-@,$P`@;7H,$P`B.
- M9BY2BR!+4HL0$$B`.@!G'B!*4HH0A;I\`")F$`P3`")F!%*+8`9"*O__8`)@C
- MUF`X($M2BQ`02(`Z`&<FNGP`(&<@NGP`"6<:NGP`#&<4NGP`#6<.NGP`"F<(F
- M($I2BA"%8,X@2E**0A!*168"4XM2;(*(8`#_6D(20J<P+(*(4D!(P.6`+P!.6
- MN@Y,*4""A%!/9@A";(*(8`#^V'H`)FR"C&`>,`5(P.6`(&R"A"&+"``O"TZZ`
- M!BA20$C`U\!83U)%NFR"B&W<,`5(P.6`(&R"A$*P"`!@`/Z:(`!,[P,```0@^
- M"#(O``Q@`A#95\G__&<&4D%@`D(84<G__$YU,#Q__V`$,"\`#"!O``1*&&;\_
- M4T@B;P`(4T`0V5?(__QG`D(0("\`!$YU(&\`!"`((F\`"!#99OQ.=4Y5```O/
- M"B1M``A*$F<@($I2BA`02(`_`$ZZ!9ZP?/__5$]F"'#_)%].74YU8-P_/``*Z
- M3KH%A%1/8.Q.50``2.<.,"1M``A"ITAZ`(Y.N@V\*4""D%!/9@A,WPQP3EU.;
- M=2!M``PB:``D+RD`!$ZZ#@XH`%A/9U)(>@!M($0O*``V3KH-X"9`2H!03V<T#
- M2'@#[2\+3KH+MBP`4$]G)"`&Y8`J`"!%)6@`"`"D)48`G$AX`^U(>@`X3KH+@
- MDB5``*!03R\$3KH-K%A/+RR"D$ZZ"\!"K(*06$]@@&EC;VXN;&EB<F%R>0!7[
- M24Y$3U<`*@!.50``+P0I;0`(@F)(;0`0+RT`#$AZ`!I.N@#<.``@;()B0A`P:
- M!$_O``PH'TY=3G5.50``(&R"8E*L@F(0+0`)$(!(@,!\`/].74YU3E4``$AM7
- M``PO+0`(2'H$<$ZZ`)A/[P`,3EU.=4Y5``!(YP@@)&T`#@QM``0`$F8((&T`A
- M""@08!Q*;0`,;PP@;0`(<``P$"@`8`H@;0`(,!!(P"@`0FT`$DIM``QL$$1M'
- M``Q*A&P(1(0[?``!`!(R+0`,2,$@!$ZZ`XY![(`24XH4L```,BT`#$C!(`1.7
- MN@.$*`!FVDIM`!)G!E.*%+P`+2`*3-\$$$Y=3G5.5?\B2.<(,"1M``@F;0`,S
- M0FW_^BMM`!#__"!+4HL0$$B`.`!G``+LN'P`)68``LI"+?\P.WP``?_X.WP`7
- M(/_V.WPG$/_T($M2BQ`02(`X`+!\`"UF#D)M__@@2U*+$!!(@#@`N'P`,&803
- M.WP`,/_V($M2BQ`02(`X`+A\`"IF&"!M__Q4K?_\.U#_\B!+4HL0$$B`.`!@H
- M,D)M__)@'#`M__+!_``*T$20?``P.T#_\B!+4HL0$$B`.``P!%)`0>R`)`@P6
- M``(``&;4N'P`+F9:($M2BQ`02(`X`+!\`"IF&"!M__Q4K?_\.U#_]"!+4HL0T
- M$$B`.`!@,D)M__1@'#`M__3!_``*T$20?``P.T#_]"!+4HL0$$B`.``P!%)`#
- M0>R`)`@P``(``&;4.WP``O_PN'P`;&82($M2BQ`02(`X`#M\``3_\&`0N'P`[
- M:&8*($M2BQ`02(`X`#`$2,!@>#M\``C_[F`6.WP`"O_N8`X[?``0_^Y@!CM\C
- M__;_[C\M__!(;?\P/RW_[B\M__Q.NOWD*T#_ZC`M__!(P-&M__Q/[P`,8%H@_
- M;?_\6*W__"M0_^HO+?_J3KH"##M`__!83V!*(&W__%2M__PX$$'M_R\K2/_JF
- M$(1@*)"\````8V?B4X!GE)"\````"V<`_W19@&>T58!G`/]R5X!G`/]T8,Q!2
- M[?\PD>W_ZCM(__`P+?_PL&W_]&\&.VW_]/_P2FW_^&=H(&W_Z@P0`"UG"B!M*
- M_^H,$``K9BX,;0`P__9F)E-M__(@;?_J4JW_ZA`02(`_`$Z2L'S__U1/9@IPQ
- M_TS?#!!.74YU8!8_+?_V3I*P?/__5$]F!'#_8.12;?_Z,"W_\E-M__*P;?_P8
- M;MQ";?_N8"`@;?_J4JW_ZA`02(`_`$Z2L'S__U1/9@1P_V"P4FW_[B!M_^I*M
- M$&<*,"W_[K!M__1MSC`M_^[1;?_Z2FW_^&8H8!@_/``@3I*P?/__5$]F!G#_N
- M8`#_>%)M__HP+?_R4VW_\K!M__!NVF`6/P1.DK!\__]43V8&</]@`/]24FW_2
- M^F``_0HP+?_Z8`#_0DCG2`!"A$J`:@1$@%)$2H%J!D2!"D0``6$^2D1G`D2`0
- M3-\`$DJ`3G5(YT@`0H1*@&H$1(!21$J!:@)$@6$:(`%@V"\!81(@`2(?2H!.&
- M=2\!808B'TJ`3G5(YS``2$%*068@2$$V`30`0D!(0(##(@!(0#("@L,P`4)!K
- M2$%,WP`,3G5(028!(@!"04A!2$!"0'0/T(#3@;:!8@22@U)`4<K_\DS?``Q.G
- M=2!O``0@"$H89OR1P"`(4X!.=4Y5``!(;("\/RT`"$ZZ``A<3TY=3G5.50``6
- M+P0X+0`(+RT`"C\$3KH`,+A\``I<3V8D(&T`"A`H``Q(@`@```=G%#\\__\O)
- M+0`*3KH`]%Q/*!].74YU8/A.50``+PHD;0`*(%*QZ@`$91@P+0`(P'P`_S\`/
- M+PI.N@#(7$\D7TY=3G4@4E*2$"T`"1"`2(#`?`#_8.A.50``+PI![("F)$@@7
- M2M7\````%B\(81!83T'L@EZUR&7J)%].74YU3E4``$CG""`D;0`(>``@"F8*O
- M</],WP003EU.=4HJ``QG4`@J``(`#&<,/SS__R\*85(X`%Q/$"H`#4B`/P!.J
- MN@3NB$`(*@`!``Q43V<*+RH`"$ZZ`BY83P@J``4`#&<2+RH`$DZZ`L`O*@`2C
- M3KH"%%!/0I)"J@`$0JH`"$(J``PP!&"03E7__DCG""`D;0`(0?K_1BE(@I0(P
- M*@`$``QG"G#_3-\$$$Y=3G4(*@`"``QG,"`2D*H`"#@`/P0O*@`($"H`#4B`]
- M/P!.N@*`L$103V<0".H`!``,0I)"J@`$</]@P`QM__\`#&80"*H``@`,0I)"W
- MJ@`$<`!@J$JJ``AF""\*3KH`FEA/#&H``0`09BH;;0`-__\_/``!2&W__Q`JE
- M``U(@#\`3KH"(K!\``%03V:@,"T`#&``_VHDJ@`(,"H`$$C`T*H`""5```0(_
- MZ@`"``P@4E*2$"T`#1"`2(#`?`#_8`#_/DY5```O"D'L@*8D2$HJ``QG&-7\S
- M````%D'L@EZUR&4(<``D7TY=3G5@XD*20JH`!$*J``@@"F#J3E7__"\*)&T`$
- M"#\\!`!.N@#`*T#__%1/9A@U?``!`!`@2M'\````#B5(``@D7TY=3G4U?`0`X
- M`!`(Z@`!``PE;?_\``@0*@`-2(`_`$ZZ`.)*0%1/9P8`*@"```Q@SDY5``!(%
- MYP`P)&R"9F`4)E(@*@`$4(`O`"\*3KH%0%!/)$L@"F;H0JR"9DS?#`!.74YU/
- M3E4``"\*0?K_QBE(@IA"IR`M``A0@"\`3KH$XB1`2H!03V8(<``D7TY=3G4D2
- MK()F)6T`"``$*4J"9B`*4(!@YDY5``!P`#`M``@O`&&R6$].74YU3E4``$CGN
- M`#"7RR1L@F9@#B!M``A1B+'*9Q(F2B12(`IF[G#_3-\,`$Y=3G4@"V<$)I)@`
- M!"E2@F8@*@`$4(`O`"\*3KH$DG``4$]@V$Y5```O"C`M``C!_``&)$#5[()VS
- M2FT`"&T.,"T`"+!L@EYL!$J29@XY?``"@IQP_R1?3EU.=3`M``C!_``&(&R"&
- M=B\P"`!.N@*P2H!83V<$<`%@`G``8-A.50``+RT`"$ZZ`GI*@%A/9@Y.N@*$L
- M.4""G'#_3EU.=7``8/A.50``2.<,(#@M``A.N@!P,`3!_``&)$#5[()V2D1MN
- M"KAL@EYL!$J29A`Y?``"@IQP_TS?!#!.74YU,"H`!,!\``-F"CE\``6"G'#_U
- M8.1P`#`M``XO`"\M``HO$DZZ`DPJ`+"\_____T_O``QF#$ZZ`@0Y0(*<</]@-
- MN"`%8+1.5?_\2'@0`$*G3KH#_"M`__P(```,4$]G$DIL@GYF""`M__Q.74YU[
- M3KH`!G``8/1.50``2'@`!$AZ`!Q.N@'B+P!.N@'H/SP``4ZZ``Y/[P`.3EU.Y
- M=5Y#"@!.50``2JR"E&<&(&R"E$Z0/RT`"$ZZ``A43TY=3G5.5?_\+P0P+0`('
- M2,`K0/_\2JR"=F<H>`!@"C\$3KH`T%1/4D2X;()>;?`P+()>P?P`!B\`+RR"-
- M=DZZ`MY03TJL@IAG!B!L@IA.D$JL@IYG"B\L@IY.N@&(6$]*K(*B9PHO+(*B"
- M3KH!>%A/2JR"IF<*+RR"IDZZ`6A83RQX``0(+@`$`2EG%"\-2_H`"DZN_^(JK
- M7V`&0J?S7TYS2JR"@&8P2JR"C&<H,"R"BDC`+P`O+(*,3KH"9#`L@HA20$C`8
- MY8`O`"\L@H1.N@)03^\`$&`.3KH".B\L@H!.N@*J6$\@+?_\+FR":DYU*!].M
- M74YU3E4``$CG#B`X+0`(,`3!_``&)$#5[()V2D1M"KAL@EYL!$J29A`Y?``"C
- M@IQP_TS?!'!.74YU""H`!P`$9@@O$DZZ``Y83T*2<`!@XD[Z``(B+P`$+&R""
- M<D[N_]PO!$SO`!X`""QL@G).KO]V*!].=2(O``0L;()R3N[_@B(O``0L;()RC
- M3N[_N"QL@G).[O_*+&R"<D[N_WPB+P`$+&R"<D[N_RA.^@`"3.\`!@`$+&R"T
- M<D[N_^).^@`"+&R"<D[N_\1.^@`"3.\`#@`$+&R"<D[N_]!(YP$$3.\@@``,M
- M+&R";DZN_Y1,WR"`3G5.^@`"(F\`!"QL@FY.[OYB3.\#```$("\`#"QL@FY.;
- M[OV03E4``$CG""!(>/__3KH`T"@`L+S_____6$]F"G``3-\$$$Y=3G5(>0`!1
- M``%(>``B3KH`N"1`2H!03V8,+P1.N@#L<`!83V#6)6T`"``*%6T`#P`)%7P`E
- M!``(0BH`#A5$``]"ITZZ`)8E0``02JT`"%A/9PHO"DZZ`%I83V`*2&H`%$ZZ[
- M`,183R`*8)).50``+PHD;0`(2JH`"F<(+PI.N@#86$\5?`#_``@E?/____\`>
- M%'``$"H`#R\`3KH`<$AX`"(O"DZZ`%)/[P`,)%].74YU(F\`!"QL@FY.[OZ>9
- M("\`!"QL@FY.[OZV3OH``DSO``,`!"QL@FY.[O\Z3OH``B)O``0L;()N3N[^U
- MVD[Z``(L;()N3N[_?$[Z``(B;P`$("\`""QL@FY.[O\N("\`!"QL@FY.[OZP/
- M3OH``B!O``0L;()N3N[^C"!O``0@B%B00J@`!"%(``A.=2QL@FXB;P`$("\`<
- M"$[N_=A,[P,```0L;()N3N[^DB)O``0L;()N3N[^F$[Z``(B;P`$+&R";D[N!
- M_H9,[P`#``0L;()N3N[^SD[Z``(@;P`$+&R";D[N_H!,[P,```0L;(*03N[_<
- MH"!O``0L;(*03N[_IB!O``0L;(*03N[_L@```^P````!`````0``!'``````-
- M```#\@```^H```"8&UM#``@``````$[Y`````#`Q,C,T-38W.#EA8F-D968`D
- M```@("`@("`@("`P,#`P,"`@("`@("`@("`@("`@("`@()!`0$!`0$!`0$!`@
- M0$!`0$`,#`P,#`P,#`P,0$!`0$!`0`D)"0D)"0$!`0$!`0$!`0$!`0$!`0$!_
- M`0$!0$!`0$!`"@H*"@H*`@("`@("`@("`@("`@("`@("`@)`0$!`(```````'
- M```````````!``````$``````````````````````0$````!````````````%
- M``````````$"`````0``````````````````````````````````````````$
- M`````````````````````````````````````````````````````````````
- M`````````````````````````````````````````````````````````````
- M`````````````````````````````````````````````````````````````
- M`````````````````````````````````````````````````````````````
- M`````````````````````````````````````````````````````````````
- M`````````````````````````````````````````````````````````````
- M`````````````````````````````````````````````````````````````
- M```````````````````````````````````````````4``````/R```#ZP``W
- &``$```/RV
- ``
- end
- size 6396
- SHAR_EOF
- # End of shell archive
- exit 0
- --
- Bob Page, U of Lowell CS Dept. page@swan.ulowell.edu ulowell!page
- Have five nice days.
-